﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ImageOptimizationTest.Optimization
{
    class ImageOptimizationHelper
    {
        public static BitmapImage CreateImageWithoutColorProfile(Uri uri)
        {
            var bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
            bitmapImage.UriSource = uri ?? throw new ArgumentNullException(nameof(uri));
            bitmapImage.EndInit();
            return bitmapImage;
        }

        /// <summary>
        /// 指定 <see cref="BitmapImage"/> 是否包含 Alpha 透明通道或者灰度通道。
        /// </summary>
        /// <returns></returns>
        public static bool IsContainsAlphaOrGrayChannel(BitmapImage bitmapImage)
        {
            // [PixelFormats 类(System.Windows.Media) | Microsoft Docs]
            // (https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.media.pixelformats)
            if (bitmapImage.Format == PixelFormats.Pbgra32 ||
                bitmapImage.Format == PixelFormats.Prgba128Float ||
                bitmapImage.Format == PixelFormats.Prgba64 ||
                bitmapImage.Format == PixelFormats.Rgba128Float ||
                bitmapImage.Format == PixelFormats.Rgba64 ||
                bitmapImage.Format == PixelFormats.Bgra32 ||
                bitmapImage.Format == PixelFormats.Gray16 ||
                bitmapImage.Format == PixelFormats.Gray2 ||
                bitmapImage.Format == PixelFormats.Gray32Float ||
                bitmapImage.Format == PixelFormats.Gray4 ||
                bitmapImage.Format == PixelFormats.Gray8)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 尝试计算最终输出的图片大小，如果图片超过限定值，则会减小图片分辨率
        /// </summary>
        /// <param name="filePath">图片路径</param>
        /// <param name="maxSize">最大图片尺寸</param>
        /// <param name="size">输出尺寸</param>
        /// <returns>是否计算成功</returns>
        public static bool TryCalcOutputImageSize(string filePath, Size maxSize, out Size size)
        {
            var bitmapImage = CreateImageWithoutColorProfile(new Uri(filePath, UriKind.RelativeOrAbsolute));
            double maxPixels = maxSize.Width * maxSize.Height;

            int imagePixelWidth;
            int imagePixelHeight;

            try
            {
                //针对图片损坏等异常处理
                imagePixelWidth = bitmapImage.PixelWidth;
                imagePixelHeight = bitmapImage.PixelHeight;
                if (bitmapImage.CanFreeze)
                {
                    bitmapImage.Freeze();
                }
            }
            catch (Exception ex)
            {
                // IO.Log.Error(ex);
                size = Size.Empty;
                return false;
            }

            if (imagePixelWidth * imagePixelHeight <= maxPixels)
            {
                size = new Size(imagePixelWidth, imagePixelHeight);
            }
            else
            {
                var fixWidth = (int)Math.Sqrt(maxPixels * imagePixelWidth / imagePixelHeight);
                var fixHeight = (int)Math.Sqrt(maxPixels * imagePixelHeight / imagePixelWidth);
                size = new Size(fixWidth, fixHeight);
            }
            return true;
        }

        /// <summary>
        /// 将 <see cref="BitmapSource"/> 存储为 Jpg 的图片文件。
        /// </summary>
        /// <param name="bitmap">要转换的 <see cref="BitmapSource"/> 实例。</param>
        /// <param name="qualityLevel">JPG 图片的质量:[1,100]</param>
        /// <param name="destDir">目标文件夹。</param>
        public static string SaveToJpgFile(BitmapSource bitmap, int qualityLevel, string destDir)
        {
            if (bitmap == null)
            {
                throw new ArgumentNullException(nameof(bitmap));
            }

            Directory.CreateDirectory(destDir);
            var fileName = Path.Combine(destDir, $"{Guid.NewGuid()}.jpg");

            if (qualityLevel < 1)
            {
                qualityLevel = 1;
            }
            if (qualityLevel > 100)
            {
                qualityLevel = 100;
            }

            JpegBitmapEncoder encoder = new JpegBitmapEncoder { QualityLevel = qualityLevel };

            encoder.Frames.Add(BitmapFrame.Create(bitmap));
            using (Stream stream = File.Create(fileName))
            {
                encoder.Save(stream);
            }

            return fileName;
        }

        /// <summary>
        /// 将 <see cref="BitmapSource"/> 存储为 Png 的图片文件。
        /// </summary>
        /// <param name="bitmap">要转换的 <see cref="BitmapSource"/> 实例。</param>
        /// <param name="destDir">目标文件夹。</param>
        public static string SaveToPngFile(BitmapSource bitmap, string destDir)
        {
            if (bitmap == null)
            {
                throw new ArgumentNullException(nameof(bitmap));
            }

            Directory.CreateDirectory(destDir);
            var fileName = Path.Combine(destDir, $"{Guid.NewGuid()}.png");

            PngBitmapEncoder encoder = new PngBitmapEncoder();

            encoder.Frames.Add(BitmapFrame.Create(bitmap));
            using (Stream stream = File.Create(fileName))
            {
                encoder.Save(stream);
            }

            return fileName;
        }
    }
}
